package com.esd.device.controller;

import com.esd.common.pojo.R;
import com.esd.device.entity.ChannelType;
import com.esd.device.entity.Device;
import com.esd.device.entity.DeviceChannel;
import com.esd.device.entity.Gateway;
import com.esd.device.entity.vo.DeviceVo;
import com.esd.device.service.ChannelTypeService;
import com.esd.device.service.DeviceChannelService;
import com.esd.device.service.DeviceService;
import com.esd.device.service.GatewayService;
import com.esd.device.task.DeviceConstants;
import com.esd.device.utils.NumberUtils;
import com.esd.device.utils.ResultUtils;
import com.esd.device.utils.Tcp_Utils_Nio;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@RestController
@RequestMapping("resistance/operation")
public class ResistanceOperationController extends BaseOperationController {
    @Autowired
    private GatewayService gatewayService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private Tcp_Utils_Nio tcp_utils;

    // 旧版开启或者关闭声音
    @PostMapping("old/soundOn/{status}")
    public R soundOn(@RequestBody DeviceVo deviceVo, @PathVariable String status) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 01 05" + " " + status;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() +
                    (status.equals("00") ? "关闭" : "开启") +
                    "声音成功！！");
        }
    }
    // 旧版的开启警报 (没什么作用)
    @PostMapping("/old/screenOn/{status}")
    public R screenOn(@RequestBody DeviceVo deviceVo, @PathVariable String status){
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 01 03" + " " + status;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() +
                    (status.equals("00") ? "关闭" : "开启") +
                    "屏幕显示成功！！");
        }
    }

    // 旧版的设置工作时间 (3通道有用)
    @PostMapping("old/setWorkTime/{timeStr}")
    public R setWorkTime(
            @PathVariable String timeStr,
            @RequestBody DeviceVo deviceVo
    ) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        StringBuilder commandStr = new StringBuilder(hexString + " " + "06 03 23");
        String[] ss = timeStr.split("-");
        for (String s : ss) {
            String temp = NumberUtils.intToHexString(Integer.parseInt(s), 2);
            commandStr.append(" ").append(temp);
        }
        R r = sendCommandForOperation(deviceVo, commandStr.toString(), tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() +
                    "设置工作时间成功！！");
        }
    }

    // 旧版的设置阀值
    // 三通道和双通道的也有区别 （这里是双通道的终端设置阀值）
    @PostMapping("old/setScale/{scale}/{start}")
    public R setScale(
            @RequestBody DeviceVo deviceVo,
            @PathVariable String scale,
            @PathVariable String start // 双通道开始位置 11 （16进制）
            // 三通道要分别为每个通道单独设置阀值，开始位置分别为11、15、19 （16进制）
    ) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 04 " + start;
        String[] ss = scale.split("-");
        String s1 = NumberUtils.intToHexString(Integer.parseInt(ss[0]), 4);
        String s2 = NumberUtils.intToHexString(Integer.parseInt(ss[1]), 4);
        s1 = new StringBuilder(s1).insert(2, " ").toString();
        s2 = new StringBuilder(s2).insert(2, " ").toString();
        commandStr = commandStr + " " + s2 + " " + s1;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            String channelNum = "";
            if (start.equals("11")) {
                channelNum = "通道一";
            }
            if (start.equals("15")) {
                channelNum = "通道二";
            }
            if (start.equals("19")) {
                channelNum = "通道三";
            }
            if (deviceVo.getDeviceTypeName().endsWith("接地电阻仪（3通道）"))
                return R.ok("终端" + deviceVo.getStationId() + channelNum + "阀值设置成功！！");
            else
                return R.ok("终端" + deviceVo.getStationId() + "阀值设置成功！！");
        }
    }

    // 旧版的同步时间 （三通道的可用）
    @PostMapping("old/setTime")
    public R setTime(@RequestBody DeviceVo deviceVo) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 03 00";
        LocalDateTime now = LocalDateTime.now();
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();
        commandStr = commandStr
                + " " + NumberUtils.intToHexString(hour, 2)
                + " " + NumberUtils.intToHexString(minute, 2)
                + " " + NumberUtils.intToHexString(second, 2);
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() + "时间设置成功！！");
        }
    }

    // 还得看网关存不存在、还得修改数据库绑定的网关
    @PostMapping("old/setSignalChannel/{change_gatewayId}")
    public R setSignalChannel(
            @PathVariable Integer change_gatewayId,
            @RequestBody DeviceVo deviceVo
    ) {
        if (change_gatewayId.intValue() == deviceVo.getGatewayId().intValue()) {
            return R.error("修改前和修改后网关及信道都相同，无需修改！！");
        }
        Gateway gateway1 = gatewayService.getById(change_gatewayId);
        Device device = deviceService.getById(deviceVo.getDeviceId());
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String sc = NumberUtils.intToHexString(gateway1.getSignalChannel(), 2);
        String commandStr = hexString + " " + "06 01 04" + " " + sc;
        String resultStr = "";
        //修改信道（无响应值） 如何确定终端未失联
        ReentrantLock reentrantLock = DeviceConstants.LockMap.get(deviceVo.getServerIp());
        reentrantLock.lock();
        try {
            resultStr = tcp_utils.sendCommand(deviceVo.getServerIp(), deviceVo.getServerPort(), commandStr, 600);
        } catch (Exception e) {
            log.error("加锁失败！！ {}", e.getMessage());
        } finally {
            reentrantLock.unlock();
        }
        if (resultStr.equals("error")) {
            return R.error("请检查网关是否正常工作！！");
        }
        device.setGatewayId(gateway1.getGatewayId());
        device.setSignalChannel(gateway1.getSignalChannel());
        deviceService.updateById(device);
        return R.ok("终端" + deviceVo.getStationId() + "信道成功修改为" + gateway1.getSignalChannel() + "！！");
    }

    @PostMapping("/soundOn/{status}")
    public R newScreenOn(@RequestBody DeviceVo deviceVo, @PathVariable String status){
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 07 01" + " " + status;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() +
                    (status.equals("00") ? "关闭" : "开启") +
                    "声音成功！！");
        }
    }

    @PostMapping("/lockKey/{status}")
    public R lockKey(@RequestBody DeviceVo deviceVo, @PathVariable String status){
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 08 01" + " " + status;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() + "按键" +
                    (status.equals("01") ? "上锁" : "解锁") +
                    "成功！！");
        }
    }

    @PostMapping("/setSignalChannel/{change_gatewayId}")
    public R newSetSignalChannel(
            @PathVariable Integer change_gatewayId,
            @RequestBody DeviceVo deviceVo
    ) {
        if (change_gatewayId.intValue() == deviceVo.getGatewayId().intValue()) {
            return R.error("修改前和修改后网关及信道都相同，无需修改！！");
        }
        Gateway gateway1 = gatewayService.getById(change_gatewayId);
        Device device = deviceService.getById(deviceVo.getDeviceId());
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String sc = NumberUtils.intToHexString(gateway1.getSignalChannel(), 2);
        String commandStr = hexString + " " + "06 06 01" + " " + sc;
        String resultStr = "";
        //修改信道（无响应值） 如何确定终端未失联
        ReentrantLock reentrantLock = DeviceConstants.LockMap.get(deviceVo.getServerIp());
        reentrantLock.lock();
        try {
            resultStr = tcp_utils.sendCommand(deviceVo.getServerIp(), deviceVo.getServerPort(), commandStr, 400);
        } catch (Exception e) {
            log.error("加锁失败！！ {}", e.getMessage());
        } finally {
            reentrantLock.unlock();
        }
        if(ResultUtils.checkResult(commandStr , resultStr)){
            device.setGatewayId(gateway1.getGatewayId());
            device.setSignalChannel(gateway1.getSignalChannel());
            deviceService.updateById(device);
            return R.ok("终端" + deviceVo.getStationId() + "信道成功修改为" + gateway1.getSignalChannel() + "！！");
        }else if (resultStr.equals("error")) {
            return R.error("请检查网关是否正常工作！！");
        }else if (resultStr.isEmpty()){
            return R.error("无返回数据，请检查终端是否正常运行？");
        }else {
            return R.error("返回数据有误，请检查终端和网关！！") ;
        }

    }

    @PostMapping("/setTime")
    public R newSetTime(@RequestBody DeviceVo deviceVo) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 00 06";

        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear()%2000;
        int month = now.getMonthValue() ;
        int day = now.getDayOfMonth() ;
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();
        commandStr = commandStr
                + " " + NumberUtils.intToHexString(year, 2)
                + " " + NumberUtils.intToHexString(month, 2)
                + " " + NumberUtils.intToHexString(day, 2)
                + " " + NumberUtils.intToHexString(hour, 2)
                + " " + NumberUtils.intToHexString(minute, 2)
                + " " + NumberUtils.intToHexString(second, 2);
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() + "时间设置成功！！");
        }
    }

    @PostMapping("/setWorkTime/{channelType}/{timeStr}")
    public R newSetWorkTime(
            @PathVariable String timeStr,
            @PathVariable String channelType , // 通道类型
            @RequestBody DeviceVo deviceVo
    ) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        StringBuilder commandStr = new StringBuilder(hexString + " " + "06" + " " + channelType + " 06");
        String[] ss = timeStr.split("-");
        for (String s : ss) {
            String temp = NumberUtils.intToHexString(Integer.parseInt(s), 2);
            commandStr.append(" ").append(temp);
        }
        R r = sendCommandForOperation(deviceVo, commandStr.toString(), tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() +
                    "设置工作时间成功！！");
        }
    }

    @PostMapping("/setScale/{scale}/{channelType}")
    public R newSetScale(
            @RequestBody DeviceVo deviceVo,
            @PathVariable String scale,
            @PathVariable String channelType  // 通道类型
    ) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 " + channelType + " 04";
        String[] ss = scale.split("-");
        String s1 = NumberUtils.intToHexString(Integer.parseInt(ss[0]), 4);
        String s2 = NumberUtils.intToHexString(Integer.parseInt(ss[1]), 4);
        s1 = new StringBuilder(s1).insert(2, " ").toString();
        s2 = new StringBuilder(s2).insert(2, " ").toString();
        commandStr = commandStr + " " + s2 + " " + s1;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            return R.ok("终端" + deviceVo.getStationId() + "阀值设置成功！！");
        }
    }

    @Autowired
    private ChannelTypeService channelTypeService ;
    @PostMapping("/setChannelType/{channelType}/{channel}")
    public R newSetChannelType(
            @RequestBody DeviceVo deviceVo,
            @PathVariable String channelType,
            @PathVariable String channel  // 通道类型
    ) {
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 " + channel + " 01 " + channelType;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            String channelTypeName ;
            if (channelType.equals("01")){
                channelTypeName = "ESD手环";
            }else if (channelType.equals("02")){
                channelTypeName = "台垫接地";
            }else {
                channelTypeName = "设备接地";
            }
            int channelNum ;
            switch (channel) {
                case "0A":
                    channelNum = 0;
                    break;
                case "0B":
                    channelNum = 1;
                    break;
                case "0C":
                    channelNum = 2;
                    break;
                default:
                    channelNum = 3;
                    break;
            }
            List<DeviceChannel> list = deviceChannelService.getListByDeviceId(deviceVo.getDeviceId());
            ChannelType channelType1 = channelTypeService.getChannelTypeByName(channelTypeName) ;
            if (channelType1 == null){
                return R.error("数据库中没有该通道类型数据！！") ;
            }else{
                DeviceChannel deviceChannel = list.get(channelNum);
                deviceChannel.setChannelTypeId(channelType1.getChannelTypeId());
                deviceChannelService.updateById(deviceChannel) ;
            }
            return R.ok("终端" + deviceVo.getStationId() + "通道类型设置成功！！");
        }
    }

    @Autowired
    private DeviceChannelService deviceChannelService ;

    @PostMapping("/channelOn/{num}")
    public R newChannelOn(
            @RequestBody DeviceVo deviceVo,
            @PathVariable Integer num
    ) throws InterruptedException {
        if(num <= 0){
            return R.error("不能关闭所有通道！！");
        }
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String status = NumberUtils.intToHexString(num, 2);
        String commandStr = hexString + " " + "06 09 01 " + status;
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            String binary = NumberUtils.hexToBinary(status, 4);
            List<DeviceChannel> list = deviceChannelService.getListByDeviceId(deviceVo.getDeviceId());
            for (int i = 0; i < list.size(); i++) {
                DeviceChannel deviceChannel = list.get(i);
                if (binary.charAt(binary.length()-1-i) == '1'){
                    deviceChannel.setEnabled(true);
                    deviceChannelService.updateById(deviceChannel);
                }else {
                    deviceChannel.setEnabled(false);
                    deviceChannelService.updateById(deviceChannel);
                }
            }
            return R.ok("终端" + deviceVo.getStationId() + "通道启用或关闭成功！！");
        }
    }

    @PostMapping("/infrared/{status}")
    public R newChannelOn(
            @RequestBody DeviceVo deviceVo,
            @PathVariable String status
    ){
        String hexString = NumberUtils.longToHexString(Long.parseLong(deviceVo.getStationId()), 8);
        String commandStr = hexString + " " + "06 28 00 " + status + " 00 00 00";
        R r = sendCommandForOperation(deviceVo, commandStr, tcp_utils);
        if (r.getCode() == 500) {
            return r;
        } else {
            String statusStr = status.equals("00")?"关闭":"开启";
            return R.ok("终端" + deviceVo.getStationId() + statusStr + "红外感应成功！！");
        }
    }

}
